﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Media;
using Microsoft.Xna.Framework.Audio;
using Rescue_of_the_Dwarvenzombies.SceneObjects.GameObjects;
using GameLibrary;
using Rescue_of_the_Dwarvenzombies.SceneObjects.GameObjects.Characters;
using Rescue_of_the_Dwarvenzombies.SceneObjects.GameObjects.Characters.Enemies;

namespace Rescue_of_the_Dwarvenzombies.Scene
{
    /// <summary>
    /// SoundManager is responsible for playing the apropriate sounds and storing all the sounds in a soundbank.
    /// </summary>
    /// <remarks></remarks>
    class SoundManager : ISoundManager
    {
        /// <summary>
        /// Sound bank for the zombie enemies
        /// </summary>
        private Dictionary<Constant.Action, SoundEffect> _zombieBank;
        /// <summary>
        /// Sound bank for the dwarves (actual players)
        /// </summary>
        private Dictionary<Constant.Action, SoundEffect> _dwarfBank;
        /// <summary>
        /// Sound bank for the weapons
        /// </summary>
        private Dictionary<Constant.Action, SoundEffect> _weaponBank;
        /// <summary>
        /// Sound bank accumilating all the individual sound banks to be treated as a whole
        /// </summary>
        private Dictionary<Type, Dictionary<Constant.Action, SoundEffect>> _soundBanks;
        /// <summary>
        /// 
        /// </summary>
        private Game _game;

        /// <summary>
        /// Initializes a new instance of the SoundManager class.
        /// </summary>
        /// <param name="game">Game is passed to get hold of the gameservices.</param>
        /// <remarks></remarks>
        public SoundManager(Game game) {
            _game = game;

            //creating individual banks for the objects, actions are used to match with sound
            //add to each individual list to create more eventsounds for each object
            _zombieBank = new Dictionary<Constant.Action, SoundEffect> { { Constant.Action.Die, _game.Content.Load<SoundEffect>("Sound/Pain") },
                                                                         { Constant.Action.TakeDamage, _game.Content.Load<SoundEffect>("Sound/TakeDamage") } };

            _weaponBank = new Dictionary<Constant.Action, SoundEffect> { { Constant.Action.Attack, _game.Content.Load<SoundEffect>("Sound/throwing") } };

            //aggregating all the individual soundbanks into a complete soundbank
            _soundBanks = new Dictionary<Type, Dictionary<Constant.Action, SoundEffect>>();

            //objecttype is matched with its corresponding soundbank so it can be used as a key
            _soundBanks.Add(typeof(Zombie), _zombieBank);

            _soundBanks.Add(typeof(Player), _weaponBank);

            //song being played during game
            Song song = _game.Content.Load<Song>("Sound/BGSound");
            MediaPlayer.Play(song);
            MediaPlayer.IsRepeating = true;
        }

        /// <summary>
        /// Plays the specified sound based on game object and it's position on the screen.
        /// </summary>
        /// <param name="gameObject">The game object used as a key for the soundbank.</param>
        /// <param name="action">action being performed used as a key for the soundbank.</param>
        /// <remarks></remarks>
        public void Play(GameObject gameObject, Constant.Action action)
        {
            SoundEffectInstance soundEffectInstance = _soundBanks[gameObject.GetType()][action].CreateInstance();
            soundEffectInstance.IsLooped = false;
            ICamera camera = (ICamera)_game.Services.GetService(typeof(ICamera));

            soundEffectInstance.Pan = MathHelper.Clamp((((gameObject.Position.X - camera.Position.X) / _game.GraphicsDevice.Viewport.Width) * 2f) - 1, 0, 1);

            soundEffectInstance.Play();
        }
    }
}
